package br3akr.DeadlyDinnerParty.Server.Actions;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

import br3akr.DeadlyDinnerParty.Server.Engine.Session;
import br3akr.DeadlyDinnerParty.Server.Exceptions.DeadlyDinnerPartyException;
import br3akr.DeadlyDinnerParty.Server.World.Area;
import br3akr.DeadlyDinnerParty.Server.World.Exit;
import br3akr.DeadlyDinnerParty.Server.World.GameCharacter;

public class ListenAction extends Action {
	boolean actionComplete;
	private ActionResponse actionResponse;
	public static final Set<String> keywords;
	static {
		Set<String> tempKeywords = new HashSet<String>();
		tempKeywords.add("Listen");
		tempKeywords.add("Li");
		keywords = Collections.unmodifiableSet(tempKeywords);
	}

	public ListenAction() {
		super("Listen", false);
	}

	public ActionResponse doAction(String action, Session session) throws DeadlyDinnerPartyException {
		StringTokenizer tokenizedAction = new StringTokenizer(action);
		String keyword = tokenizedAction.nextToken();
		String param1 = null;
		
		if (tokenizedAction.hasMoreTokens()) {
			param1 = tokenizedAction.nextToken();
		}
		
		if (param1 == null) {
			throw new DeadlyDinnerPartyException ("Listen to who, or what?");
		}
		
		actionResponse = new ActionResponse();
		GameCharacter actor = session.getCharacter();
		actionResponse.setActingCharacter(actor);
		Area location = actor.getLocation();
		StringBuilder newDesc = new StringBuilder();
		
		switch (keyword.toLowerCase()) {
		case "listen":
		case "li":
			try {
				Exit exit = location.getExit(Exit.getDirection(param1));
				
				if (exit != null) {

					Area listenToLocation = exit.getExitArea(location);

					if (listenToLocation != null) {
						Set<GameCharacter> localOnlookers = location.getAreaOnlookers(actor, null);
						actionResponse.addAffectedArea(location);
						
						if (actor.getListeningToCharacter() != null) {
							newDesc.append("You stop listening to " + actor.getListeningToCharacter().getName() + ".\n");
						}
						
						if (actor.getListeningToArea() != null) {
							newDesc.append("You stop listening to " + actor.getListeningToArea().getName() + ".\n");
						}
						
						actor.stopListening();
						listenToLocation.addListener(actor);
						
						actor.setListenArea(listenToLocation);
						
						actionResponse.addOnlookers(localOnlookers,
								actor.getName()
										+ " begins listening to "
										+ listenToLocation.getName() + " to the " + exit.getExitDirection(location) + ".");
						actionResponse
								.setActingCharacterDescription(newDesc + "You begin listening to "
										+ listenToLocation.getName() + " to the " + exit.getExitDirection(location) + ".");

					} else {
						actionResponse
								.setActingCharacterDescription("There is no exit "
										+ exit);
					}
				} else {
					GameCharacter listenToCharacter = location.getCharacter(param1);

					if (listenToCharacter != null && !listenToCharacter.isHiddenFrom(actor)) {
						listenToCharacter.addListener(actor);
						
						if (actor.getListeningToCharacter() != null) {
							newDesc.append("You stop listening to " + actor.getListeningToCharacter().getName() + ".\n");
						}
						
						if (actor.getListeningToArea() != null) {
							newDesc.append("You stop listening to " + actor.getListeningToArea().getName() + ".\n");
						}
						
						actor.stopListening();
						actor.listenCharacter(listenToCharacter.getName());
						actionResponse
						.setActingCharacterDescription(newDesc + "You begin listening to "
								+ listenToCharacter.getName() + ".");
					} else {
						actionResponse.setActingCharacterDescription("There is no one here by the name of " + param1);
					}
				}
			} catch (DeadlyDinnerPartyException e) {
				actionResponse.setActingCharacterDescription(e.getMessage());
			}
			actionComplete = true;
			break;
		default:
			break;
		}
		return actionResponse;
	}

	public ActionResponse getActionResponse() {
		return actionResponse;
	}

	public Set<String> getKeywords() {
		return keywords;
	}
}